﻿using Mes.Domain.BoundedContext;
using AutoMapper;
using System.Transactions;
using Microsoft.EntityFrameworkCore;
using Mes.Infrastructure.Data.BoundedContext.Extensions;
using Mes.Infrastructure.Data.BoundedContext.RepositoryBase;
using Mes.Application.Common;
using Mes.Infrastructure.Data.BoundedContext.Configurations;
using Microsoft.Extensions.Options;
using Mes.Application.Common.Resource;
using Mes.Application.DTO.Inputs.MasterData;
using Mes.Application.DTO.Results.MasterData;
using Mes.Domain.BoundedContext.Entities.MasterData;
using Mes.Infrastructure.Data.BoundedContext.Repositories.MasterData;

namespace Mes.Application.Services.MasterData
{
    public class MaterialClassTypeService : IMaterialClassTypeService
    {
        private readonly IRepository<MaterialClassType> _materialClassTypeRepository;
        private readonly IMaterialClassTypeRepository _materialClassTypeRepositoryInterface;
        private readonly IMapper _mapper;
        private readonly BuiltInTypesConfiguration _builtInTypes;
        public MaterialClassTypeService(IRepository<MaterialClassType> materialClassTypeRepository, IMapper mapper, IMaterialClassTypeRepository materialClassTypeRepositoryInterface,
            IOptions<BuiltInTypesConfiguration> options)
        {
            if (materialClassTypeRepository == null || mapper == null || materialClassTypeRepositoryInterface == null)
            {
                throw new ArgumentNullException();
            }
            _materialClassTypeRepository = materialClassTypeRepository; //注入仓储类
            _mapper = mapper;
            _materialClassTypeRepositoryInterface = materialClassTypeRepositoryInterface;
            _builtInTypes = options.Value;
        }

        /// <summary>
        /// 新增物料类类型
        /// </summary>
        /// <param name="materialClassTypeInput"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task AddMaterialClassTypeAsync(MaterialClassTypeInput materialClassTypeInput)
        {
            if (await _materialClassTypeRepository.ExistsAsync(x => x.Description == materialClassTypeInput.Description))
            {
                throw new CustomException(Messages.MaterialClassTypeExist);
            }
            var materialClassType = _mapper.Map<MaterialClassType>(materialClassTypeInput);
            await _materialClassTypeRepository.AddAsync(materialClassType);
            int status = await _materialClassTypeRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 修改物料类类型
        /// </summary>
        /// <param name="materialClassTypeUpdateInput"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task UpdateMaterialClassTypeAsync(MaterialClassTypeUpdateInput materialClassTypeUpdateInput)
        {
            var materialClassType = _materialClassTypeRepository.Find(x => x.Id == materialClassTypeUpdateInput.Id);
            if (materialClassType == null)
            {
                throw new CustomException(Messages.MaterialClassTypeNotFound);
            }
            if (materialClassType.Type == _builtInTypes.BuiltInMaterialClassTypes[0] || materialClassType.Type == _builtInTypes.BuiltInMaterialClassTypes[1] || materialClassType.Type == _builtInTypes.BuiltInMaterialClassTypes[2])
            {
                throw new CustomException(Messages.BuiltInTypeCantBeEdited);
            }

            materialClassType.UpdateTime = DateTime.Now;
            materialClassType.Type = materialClassTypeUpdateInput.Type;
            materialClassType.Description = materialClassTypeUpdateInput.Description;
            materialClassType.Note = materialClassTypeUpdateInput.Note;
            _materialClassTypeRepository.Update(materialClassType);
            int status = await _materialClassTypeRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 删除物料类类型
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task DeleteMaterialClassTypeAsync(int[] ids)
        {
            using (TransactionScope ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
            {
                foreach (int id in ids)
                {
                    var materialClassType = _materialClassTypeRepository.Find(x => x.Id == id);
                    if (materialClassType == null)
                    {
                        throw new CustomException(Messages.MaterialClassTypeNotFound);
                    }

                    if (materialClassType.Type == _builtInTypes.BuiltInMaterialClassTypes[0] || materialClassType.Type == _builtInTypes.BuiltInMaterialClassTypes[1] || materialClassType.Type == _builtInTypes.BuiltInMaterialClassTypes[2])
                    {
                        throw new CustomException(Messages.BuiltInTypeCantBeEdited);
                    }

                    _materialClassTypeRepository.Delete(materialClassType);
                    int status = await _materialClassTypeRepository.SaveAsync();
                    if (status <= 0)
                    {
                        throw new CustomException(Messages.SavingFailure);
                    }
                }
                ts.Complete();
            }
        }

        /// <summary>
        /// 根据主键编号查询物料类类型
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task<MaterialClassTypeResult> GetMaterialClassTypeAsync(int id)
        {
            var materialClassType = await _materialClassTypeRepository.Query().Where(x => x.Id == id).FirstOrDefaultAsync();
            if (materialClassType == null)
            {
                throw new CustomException(Messages.MaterialClassTypeNotFound);
            }
            return _mapper.Map<MaterialClassTypeResult>(materialClassType);
        }

        /// <summary>
        /// 分页查询物料类类型
        /// </summary>
        /// <param name="materialClassTypePageInput"></param>
        /// <returns>PagedItemsData<MaterialClassTypeResult></returns>
        /// <exception cref="CustomException"></exception>
        public async Task<PagedItemsData<MaterialClassTypeResult>> GetMaterialClassTypesAsync(MaterialClassTypePageInput materialClassTypePageInput)
        {
            var materialClassType = await _materialClassTypeRepository.Query().Where(x => x.Type.Contains(materialClassTypePageInput.Type)).ToPagedAsync(materialClassTypePageInput.PagedInput);
            if (materialClassType == null)
            {
                throw new CustomException(Messages.MaterialClassTypeNotFound);
            }
            return _mapper.Map<PagedItemsData<MaterialClassTypeResult>>(materialClassType);
        }
    }
}
